package com.power.algorithm.structure.queue;

import java.util.Arrays;

/**
 * @description:
 * @author: jiangnan
 * @time: 2021/5/20 2:03 下午
 */
public class ArrayQueue<E> {

    private Object[] queue;
    private int MAX_SIZE = 10;
    private final float EXPENSION_FACTORY = 1.5f;
    private int front = 0;
    private int rear = 0;
    int size = 0;

    public ArrayQueue() {
        queue = new Object[MAX_SIZE];
    }

    /***
     * 数据迁移
     * 1. 容量满了  数据进行扩容之后  头尾指针变化
     * 2. 尾部满了  头尾指针变化
     */
    //容量满了  数据进行扩容之后  头尾指针变化
    public Object[] extension() {
        int newCapacity = Math.round(MAX_SIZE * EXPENSION_FACTORY);
        MAX_SIZE = newCapacity;
        front = 0;
        return Arrays.copyOf(queue, newCapacity);
    }

    //如果队列尾部满了  则进行数据迁移
    public void migrate() {
        // 从头部的位置 复制所有的元素到 队列开始的位置
        /**
         * arrayCopy的参数的含义
         *  Object src : 原数组
         *  int srcPos : 从元数据的起始位置开始
         *  Object dest : 目标数组
         *  int destPos : 目标数组的开始起始位置
         *  int length  : 要copy的数组的长度
         *
         * byte[]  srcBytes = new byte[]{2,4,0,0,0,0,0,10,15,50};  // 源数组
         * byte[] destBytes = new byte[5]; // 目标数组
         *
         * System.arrayCopy(srcBytes,0,destBytes ,0,5)
         * 那么这行代码的运行效果应该是 2,4,0,0,0,
         * */
        Object[] newArray = new Object[MAX_SIZE];
        System.arraycopy(queue, front, newArray, 0, size);
        queue = newArray;
        front = 0;
        rear = size - 1;
    }

    //入队操作 offer  出队操作从第0个元素开始

    /**
     * 队满的条件
     * front = 0 && rear = maxSize - 1
     * <p>
     * 队列空的条件 front = rear
     */
    public void offer(E e) {
        //如果队列满了 则进行扩容
        if (front == 0 && rear == MAX_SIZE - 1) {
            queue = extension();
        }
        //如果队列有空闲位置而尾部满了 则进行数据迁移
        if (front != 0 && rear == MAX_SIZE - 1) {
            migrate();
        }
        // 如果尾部没有满 则将元素加到尾部
        queue[rear++] = e;
        size++;
    }

    //出队列操作
    public Object poll() {
        //如果队列中没有元素 直接返回
        if (size == 0) {
            return "没有元素可以出队啦";
        }
        //如果队列中只有一个元素返回之后队列初始化为0
        if (front == rear) {
            Object res = queue[front];
            front = 0;
            rear = 0;
            return res;
        }
        //如果头尾指针不在一起  则正常的出站
        return queue[front++];
    }

    public static void main(String[] args) {

        System.out.println(0 % 4);
        ArrayQueue<Integer> arrayQueue = new ArrayQueue<>();

        for (int i = 0; i < 25; i++) {
            arrayQueue.offer(i);
           // arrayQueue.poll();
        }
    }
}
